// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.

#include "JavascriptGraphTextPropertyEditableTextBox.h"
#include "Editor/EditorWidgets/Public/STextPropertyEditableTextBox.h"
#include "Internationalization/StringTableRegistry.h"
#include "ScopedTransaction.h"
#include "../../Launch/Resources/Version.h"

#define LOCTEXT_NAMESPACE "JavascriptGraphTextPropertyEditableTextBox"

/** Allows STextPropertyEditableTextBox to edit a graph pin */
class FJavascriptEditableTextGraphPin : public IEditableTextProperty
{
public:
	FJavascriptEditableTextGraphPin(UEdGraphPin* InGraphPinObj, UJavascriptGraphTextPropertyEditableTextBox* InEditableTextBox)
		: GraphPinObj(InGraphPinObj)
		, EditableTextBox(InEditableTextBox)
	{
	}

	virtual bool IsMultiLineText() const override
	{
		return true;
	}

	virtual bool IsPassword() const override
	{
		return false;
	}

	virtual bool IsReadOnly() const override
	{
		return GraphPinObj->bDefaultValueIsReadOnly;
	}

	virtual bool IsDefaultValue() const override
	{
		FString TextAsString;
#if ENGINE_MINOR_VERSION < 22
        if (FTextStringHelper::WriteToString(TextAsString, GraphPinObj->DefaultTextValue))
        {
            return TextAsString.Equals(GraphPinObj->AutogeneratedDefaultValue, ESearchCase::CaseSensitive);
        }
        return false;
#else
		FTextStringHelper::WriteToBuffer(TextAsString, GraphPinObj->DefaultTextValue);
		return TextAsString.Equals(GraphPinObj->AutogeneratedDefaultValue, ESearchCase::CaseSensitive);
#endif
	}

	virtual FText GetToolTipText() const override
	{
		return FText::GetEmpty();
	}

	virtual int32 GetNumTexts() const override
	{
		return 1;
	}

	virtual FText GetText(const int32 InIndex) const override
	{
		check(InIndex == 0);
		return GraphPinObj->DefaultTextValue;
	}

	virtual void SetText(const int32 InIndex, const FText& InText) override
	{
		check(InIndex == 0);
		const FScopedTransaction Transaction(NSLOCTEXT("GraphEditor", "ChangeTxtPinValue", "Change Text Pin Value"));
		GraphPinObj->Modify();
		GraphPinObj->GetSchema()->TrySetDefaultText(*GraphPinObj, InText);		
		EditableTextBox->HandleOnTextCommitted(InText);
	}

	virtual bool IsValidText(const FText& InText, FText& OutErrorMsg) const override
	{
		return true;
	}

	virtual void GetStableTextId(const int32 InIndex, const ETextPropertyEditAction InEditAction, const FString& InTextSource, const FString& InProposedNamespace, const FString& InProposedKey, FString& OutStableNamespace, FString& OutStableKey) const override
	{
		check(InIndex == 0);

		OutStableNamespace = InProposedNamespace;

		if (!InProposedKey.IsEmpty())
		{
			OutStableKey = InProposedKey;
		}
		else
		{
			OutStableKey = FGuid::NewGuid().ToString();
		}

		EditableTextBox->HandleOnNamespaceKeyChanged(OutStableNamespace, OutStableKey);
	}

	virtual void RequestRefresh() override
	{
	}

private:
	UEdGraphPin* GraphPinObj;
	UJavascriptGraphTextPropertyEditableTextBox* EditableTextBox;
};

/////////////////////////////////////////////////////
// UJavascriptGraphTextPropertyEditableTextBox
UJavascriptGraphTextPropertyEditableTextBox::UJavascriptGraphTextPropertyEditableTextBox(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	STextPropertyEditableTextBox::FArguments Defaults;
	WrapTextAt = Defaults._WrapTextAt.Get();
	AutoWrapText = Defaults._AutoWrapText.Get();
	MinimumDesiredWidth = Defaults._MinDesiredWidth.Get();
	MaximumDesiredHeight = Defaults._MaxDesiredHeight.Get();

	WidgetStyle = *Defaults._Style;
}

void UJavascriptGraphTextPropertyEditableTextBox::SynchronizeProperties()
{
	Super::SynchronizeProperties();
}

void UJavascriptGraphTextPropertyEditableTextBox::ReleaseSlateResources(bool bReleaseChildren)
{
	Super::ReleaseSlateResources(bReleaseChildren);

	MyEditableTextBlock.Reset();
}

void UJavascriptGraphTextPropertyEditableTextBox::HandleOnNamespaceKeyChanged(const FString& InNamespace, const FString& InKey)
{
	MyTextProperty.Namespace = InNamespace;
	MyTextProperty.Key = InKey;
}

void UJavascriptGraphTextPropertyEditableTextBox::HandleOnTextCommitted(const FText& InText)
{
	FName TableId = NAME_None;
	FString Key;
	FTextInspector::GetTableIdAndKey(InText, TableId, Key);
	MyTextProperty.TableId = TableId;
	MyTextProperty.Namespace = FTextInspector::GetNamespace(InText).Get(FString());
	MyTextProperty.Key = FTextInspector::GetKey(InText).Get(FString());
	MyTextProperty.Value = InText.ToString();

	OnTextCommitted.Broadcast(MyTextProperty);
}

void UJavascriptGraphTextPropertyEditableTextBox::HandleOnStringTableKeyChanged(const FName& InTableId, const FString& InKey)
{
	MyTextProperty.TableId = InTableId;
	MyTextProperty.Key = InKey;
}

TSharedRef<SWidget> UJavascriptGraphTextPropertyEditableTextBox::RebuildWidget()
{
	auto defaultWidget = SNew(SBox)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("JavascriptGraphTextPropertyEditableTextBox", "JavascriptGraphTextPropertyEditableTextBox"))
		];

	if (IsDesignTime())
	{
		return RebuildDesignWidget(defaultWidget);
	}
	else
	{
		if (OnGetGraphPin.IsBound())
		{
			FJavascriptEdGraphPin GraphPin = OnGetGraphPin.Execute();

			if (GraphPin.IsValid())
			{
				if (OnGetDefaultValue.IsBound())
				{
					MyTextProperty = OnGetDefaultValue.Execute();

					if (!MyTextProperty.TableId.IsNone())
					{
						GraphPin->DefaultTextValue = FText::FromStringTable(MyTextProperty.TableId, MyTextProperty.Key);
					} else if (!MyTextProperty.Value.IsEmpty())
					{
						if (MyTextProperty.Key.IsEmpty())
						{
							MyTextProperty.Key = FGuid::NewGuid().ToString();

							OnTextCommitted.Broadcast(MyTextProperty);
						}

						GraphPin->DefaultTextValue = FText::ChangeKey(MyTextProperty.Namespace, MyTextProperty.Key, FText::FromString(MyTextProperty.Value));
					}					
				}

				MyEditableTextProperty = MakeShareable(new FJavascriptEditableTextGraphPin(GraphPin, this));

				MyEditableTextBlock = SNew(STextPropertyEditableTextBox, MyEditableTextProperty.ToSharedRef())
					.Style(&WidgetStyle)
					.WrapTextAt(WrapTextAt)
					.AutoWrapText(AutoWrapText)
					.MinDesiredWidth(MinimumDesiredWidth)
					.MaxDesiredHeight(MaximumDesiredHeight);

				return MyEditableTextBlock.ToSharedRef();;
			}
		}

		return defaultWidget;
	}
}

#undef LOCTEXT_NAMESPACE